﻿using DevExpress.Pdf.Native.BouncyCastle.Utilities;
using DevExpress.Utils.CommonDialogs;
using DevExpress.XtraEditors;
using iText.Kernel.Pdf;
using Microsoft.Win32;
using PDFQuick.Dtos;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using iText.Layout;
using iText.Layout.Element;
using iText.IO.Image;
using System.IO;
using Image = iText.Layout.Element.Image;
using iText.Kernel.Geom;
using System.Collections.Concurrent;
using System.Text.RegularExpressions;
using DevExpress.Utils;
using PDFQuick.Utils;
using PaddleOCRSharp;
using iText.IO.Font;
using iText.Kernel.Colors;
using iText.Kernel.Font;
using iText.Kernel.Pdf.Xobject;
using iText.Layout.Properties;
using System.Drawing.Drawing2D;
using DevExpress.XtraRichEdit.Model;

namespace PDFQuick
{
    public partial class Main : DevExpress.XtraEditors.XtraForm
    {
        List<FileListDto> fileListDtos = new List<FileListDto>();
        private int waitNum = 0;
        private int finishNum = 0;
        private PaddleOCREngine engine;
        private OCRStructureResult ocrResult;
        public Main()
        {
            InitializeComponent();
            //使用默认中英文V3模型
            OCRModelConfig config = null;
            //使用默认参数
            OCRParameter oCRParameter = new OCRParameter();

            //建议程序全局初始化一次即可，不必每次识别都初始化，容易报错。     
            engine = new PaddleOCREngine(config, oCRParameter);
            //识别结果对象
            ocrResult = new OCRStructureResult();

            progressBarControl1.Properties.ShowTitle = true;
            progressBarControl1.Properties.PercentView = true;

            labelControl8.Text = waitNum.ToString();
            labelControl9.Text = finishNum.ToString();
            labelControl10.Text = "0";
            labelControl11.Text = "";
            textEdit1.Text = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
        }

        private void simpleButton3_Click(object sender, EventArgs e)
        {
            fileListDtos.Clear();
            System.Windows.Forms.OpenFileDialog openFileDialog = new System.Windows.Forms.OpenFileDialog();

            var imageType = comboBoxEdit2.Text.ToLower();
            openFileDialog.Filter = $"DataBank(*.{imageType})|*.{imageType}|全部文件(*.*)|*.*";
            openFileDialog.Multiselect = true;//是否允许多选，false表示单选

            System.Windows.Forms.DialogResult dr = openFileDialog.ShowDialog();
            if (dr == System.Windows.Forms.DialogResult.OK)
            {
                //openFileDialog.FileNames 获取对话框中所有选定文件的文件名（String 类型数组），为绝对路径，类似"E:\\code\\123.xml"
                for (int i = 0; i < openFileDialog.FileNames.Count(); i++)
                {
                    System.IO.FileInfo file = new System.IO.FileInfo(openFileDialog.FileNames[i]);//如果是单选，FileName=openFileDialog.FileName
                    if (file.Extension == "." + imageType)
                    {
                        fileListDtos.Add(new FileListDto
                        {
                            Id = i + 1,
                            FileName = file.Name,
                            FolderName = System.IO.Path.GetDirectoryName(file.FullName),
                            ParentId = 0
                        });
                    }
                    else
                    {
                        MessageBox.Show("请选择JPG文件，目前仅支持对JPG数据读取!");
                        return;
                    }
                }
                treeList1.Nodes.Clear();
                treeList1.DataSource = null;
                treeList1.DataSource = fileListDtos;
                treeList1.RefreshDataSource();
                treeList1.KeyFieldName = "Id";
                treeList1.ParentFieldName = "ParentId";
                labelControl8.Text = fileListDtos.Count.ToString();
            }
        }

        private void simpleButton4_Click(object sender, EventArgs e)
        {
            fileListDtos.Clear();
            System.Windows.Forms.FolderBrowserDialog folderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog();
            System.Windows.Forms.DialogResult dr = folderBrowserDialog.ShowDialog();
            if (dr == System.Windows.Forms.DialogResult.OK)
            {
                string path = folderBrowserDialog.SelectedPath;
                var imageType = comboBoxEdit2.Text.ToLower();
                string[] strings = null;
                if (checkEdit3.Checked)
                {
                    strings = Directory.GetFiles(path, "*." + imageType, SearchOption.AllDirectories);
                }
                else
                {
                    strings = Directory.GetFiles(path, "*." + imageType, SearchOption.TopDirectoryOnly);
                }

                Array.Sort(strings, new StringArrayToCompare());
                for (int i = 0; i < strings.Count(); i++)
                {
                    System.IO.FileInfo file = new System.IO.FileInfo(strings[i]);//如果是单选，FileName=openFileDialog.FileName

                    fileListDtos.Add(new FileListDto
                    {
                        Id = i + 1,
                        FileName = file.Name,
                        FolderName = System.IO.Path.GetDirectoryName(file.FullName),
                        ParentId = 0
                    });
                }
                treeList1.Nodes.Clear();
                treeList1.DataSource = fileListDtos;
                treeList1.RefreshDataSource();
                treeList1.KeyFieldName = "Id";
                treeList1.ParentFieldName = "ParentId";
                labelControl8.Text = fileListDtos.Count.ToString();
            }
        }

        private void simpleButton5_Click(object sender, EventArgs e)
        {
            treeList1.Nodes.Clear();
        }

        private void simpleButton6_Click(object sender, EventArgs e)
        {
            System.Windows.Forms.FolderBrowserDialog folderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog();
            System.Windows.Forms.DialogResult dr = folderBrowserDialog.ShowDialog();
            if (dr == System.Windows.Forms.DialogResult.OK)
            {
                textEdit1.Text = folderBrowserDialog.SelectedPath;
            }
        }

        private Task task = null;
        CancellationTokenSource tokenSource = null;
        private void simpleButton1_Click(object sender, EventArgs e)
        {
            listBoxControl1.Items.Clear();
            simpleButton1.Enabled = false;
            simpleButton2.Enabled = true;

            progressBarControl1.Properties.Minimum = 0;
            progressBarControl1.Position = 0;
            progressBarControl1.Properties.Maximum = fileListDtos.Count;
            PdfWriter pdfWriter = null;
            PdfDocument pdfDocument = null;
            Document document = null;

            ConcurrentQueue<FileListDto> cqsellTickets = new ConcurrentQueue<FileListDto>();
            foreach (var item in fileListDtos)
            {
                cqsellTickets.Enqueue(item);
            }

            tokenSource = new CancellationTokenSource();
            task = Task.Run(() =>
            {
                var dest = "";
                var activte = "";
                var pdfName = "";
                for (int i = 0; i < fileListDtos.Count; i++)
                {
                    if (tokenSource.IsCancellationRequested)
                    {
                        pdfDocument.Close();
                        return;
                    }
                    cqsellTickets.TryDequeue(out FileListDto item);

                    string imagePath = item.FolderName + "\\" + item.FileName;
                    ImageData imageData = ImageDataFactory.Create(imagePath);
                    Image image = new Image(imageData);


                    if (activte != item.FolderName)
                    {
                        if (!string.IsNullOrEmpty(activte))
                        {
                            pdfDocument.Close();
                        }
                        activte = item.FolderName;
                        List<string> paths = item.FolderName.Split("\\").ToList();
                        pdfName = paths[paths.Count - 1];
                        var temp = paths.TakeLast((int)(spinEdit1.Value + 1)).ToArray();
                        string str = "";
                        for (int j = 0; j < temp.Count() - 1; j++)
                        {
                            str += "\\" + temp[j];
                        }
                        dest = textEdit1.Text + str;
                        if (!Directory.Exists(dest))
                        {
                            Directory.CreateDirectory(dest);
                        }
                        var pdfPath = dest + "\\" + pdfName + ".pdf";
                        listBoxControl1.Invoke(() =>
                        {
                            listBoxControl1.Items.Add(pdfPath);
                            listBoxControl1.SelectedItem = listBoxControl1.Items[listBoxControl1.Items.Count - 1];
                        });
                        pdfWriter = new PdfWriter(pdfPath);
                        pdfDocument = new PdfDocument(pdfWriter);
                        float width = image.GetImageWidth(); //获取图片的宽
                        float height = image.GetImageHeight();//获取图片的高
                        PageSize pageSize = new PageSize(PageSize.A4.GetWidth(), PageSize.A4.GetHeight()); //设置与图片大小一致
                        pdfDocument.SetDefaultPageSize(pageSize);//设置页面大小
                        document = new Document(pdfDocument);
                        document.SetMargins(0, 0, 0, 0);// 设置边距 top right botton left
                    }
                    treeList1.Invoke(() =>
                    {
                        treeList1.FocusedNode = treeList1.Nodes[i];
                    });
                    document.Add(image);


                    //生成双层pdf
                    if (checkEdit2.Checked)
                    {
                        //获取pdf中的图片
                        PdfImageXObject imageObject = (PdfImageXObject)image.GetXObject();
                        MemoryStream ms = new MemoryStream(imageObject.GetImageBytes());
                        System.Drawing.Image img = System.Drawing.Image.FromStream(ms);
                        System.Drawing.Image sbmpthum = img.GetThumbnailImage((int)PageSize.A4.GetWidth(), (int)PageSize.A4.GetHeight(), () => { return false; }, IntPtr.Zero);
                        ocrResult = engine.DetectStructure(sbmpthum);
                        //添加文字
                        //设置文字颜色
                        iText.Kernel.Colors.Color color = new DeviceRgb(0, 255, 255);
                        PdfFont pdfFont = PdfFontFactory.CreateFont(@"C:\WINDOWS\Fonts\SIMFANG.TTF", PdfEncodings.IDENTITY_H);
                        document.SetFontColor(color).SetFont(pdfFont);
                        for (int j = 0; j < ocrResult.TextBlocks.Count; j++)
                        {
                            PaddleOCRSharp.TextBlock textBlock = ocrResult.TextBlocks[j];
                            if (string.IsNullOrEmpty(textBlock.Text)) continue;
                            //textBlock.BoxPoints(leftTop,rightTop,rightBottom,leftBottom)
                            OCRPoint leftTop = textBlock.BoxPoints[0];
                            OCRPoint rightTop = textBlock.BoxPoints[1];
                            OCRPoint rightBottom = textBlock.BoxPoints[2];
                            OCRPoint leftBottom = textBlock.BoxPoints[3];

                            iText.Layout.Element.Paragraph paragraph = new iText.Layout.Element.Paragraph(textBlock.Text);
                            //根据文本长度动态设置文字大小
                            float pfontsize = (rightBottom.X - leftBottom.X) / textBlock.Text.Length;
                            paragraph.SetFontSize(pfontsize);
                            //设置透明度
                            paragraph.SetOpacity(1);
                            //document.ShowTextAligned 定位:从左到右;从下到上
                            document.ShowTextAligned(paragraph, leftBottom.X, sbmpthum.Height - leftBottom.Y, TextAlignment.LEFT);
                        }
                    }


                    progressBarControl1.Invoke(() =>
                    {
                        labelControl11.Text = imagePath;
                        labelControl8.Text = cqsellTickets.Count.ToString();
                        labelControl9.Text = (fileListDtos.Count - cqsellTickets.Count).ToString();
                        labelControl10.Text = Sec2Min(cqsellTickets.Count);
                        progressBarControl1.Position = i + 1;
                    });
                }
                pdfDocument.Close();
                simpleButton1.Invoke(() =>
                {
                    simpleButton1.Enabled = true;
                    simpleButton2.Enabled = false;
                });
                MessageBox.Show("文件转换完成！", "提示");
            }, tokenSource.Token);


        }
        private string Sec2Min(Int64 sec)
        {
            Int64 shi;
            Int64 fen;
            Int64 miao;
            if (sec < 0)
                sec = 0;
            miao = sec % 60;
            sec = sec - miao;
            sec /= 60;
            fen = sec % 60;
            sec -= fen;
            shi = sec / 60;
            return string.Format("{0:00} 时 {1:00} 分 {2:00} 秒", shi, fen, miao);
        }

        private void simpleButton2_Click(object sender, EventArgs e)
        {
            tokenSource.Cancel();
            simpleButton1.Enabled = true;
            simpleButton2.Enabled = false;
        }
    }
}